package lt.ntec.danblog.server.core;

import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.io.Writer;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.Date;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.UnavailableException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.google.inject.Injector;

@SuppressWarnings("unused")
public class FrontController extends HttpServlet {

    /**
     *
     */
    private static final long serialVersionUID = -4403943253268166062L;
    private final Logger log = Logger.getLogger(FrontController.class.getName());
    private Injector injector;

    @Override
    public void init(ServletConfig config) {
        try {
            super.init(config);
        } catch (ServletException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        }
        ServletContext context = config.getServletContext();
        injector = (Injector) context.getAttribute(Injector.class.getName());
        if (injector == null) {
            try {
                throw new UnavailableException("Guice Injector not found "
                        + "(did you forget to foo koo joo boo?)");
            } catch (UnavailableException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        injector.injectMembers(this);
    }

    public void doGet(HttpServletRequest req, HttpServletResponse rsp)
            throws ServletException, IOException {
        _handle(req, rsp);
    }

    public void doPost(HttpServletRequest req, HttpServletResponse rsp)
            throws IOException {
        _handle(req, rsp);
    }

    private void _handle(HttpServletRequest req, HttpServletResponse rsp) {
        log.info("Request: " + req.hashCode() + " <> Response: " + rsp.hashCode());

        String feature = "index";
        String action = "index";

        String uri = (req.getRequestURI());
        String[] tokens = uri.split("/");
        if (tokens.length > 1) {

            if (tokens[1] != null && tokens[1].length() != 0) {
                feature = tokens[1];
            }
        }
        if (tokens.length > 2) {
            if (tokens[2] != null && tokens[2].length() != 0) {
                action = tokens[2];
            }
        }

        try {
            String name = "com.dblog.server." + feature + ".Controller";

            String methodName = action + "Action";

            log.info("Opening: /" + feature + "/" + action);

            Class<?> cl = Class.forName(name);

            Constructor<?> constructor = cl.getConstructor(new Class[]{
                        HttpServletRequest.class, HttpServletResponse.class});

            Object controllerInstance = constructor.newInstance(new Object[]{
                        req, rsp});

            Class<?> arguments[] = new Class[]{};

            Method controllerAction = cl.getMethod(methodName, arguments);

            ServletConfig[] params = {getServletConfig()};

            // Call servlet init(ServletConfig) with config
            cl.getMethod("init", new Class[]{ServletConfig.class}).invoke(
                    controllerInstance, (Object[]) params);


            controllerAction.invoke(controllerInstance,
                    (Object[]) new Class[]{});

            req.setAttribute("contentView", "/WEB-INF/Views/" + feature + "/"
                    + action + ".jsp");

            if (rsp.isCommitted()) {
                log.info("Deny forward");
                return;
            }
            log.info("Forward to layout");

            getServletContext().getRequestDispatcher(
                    "/WEB-INF/layout/Layout.jsp").forward(req, rsp);
        } catch (ClassNotFoundException e) {
            if (e.getMessage().contains("Controller")) {
                log.warning("Page not found - Feature: " + feature + "; Action: " + action);
                req.setAttribute("contentView", "/WEB-INF/Views/error/404.jsp");
                try {
                    getServletContext().getRequestDispatcher(
                            "/WEB-INF/layout/Layout.jsp").forward(req, rsp);
                } catch (ServletException e1) {
                    // TODO Auto-generated catch block
                    e1.printStackTrace();
                } catch (IOException e1) {
                    // TODO Auto-generated catch block
                    e1.printStackTrace();
                }
            }
        } catch (Exception e) {
            log.warning("Server has caught exception");



            if (e.getMessage() != null) {
                log.warning("Message: " + e.getMessage());
            } else {
                log.warning("Null message");
            }

            log.warning("Error on " + req.getRequestURI());
            log.warning("Feature: " + feature + "; Action: " + action);
            StringWriter sw = new StringWriter();
            e.printStackTrace(new PrintWriter(sw));
            String exceptionAsString = sw.toString();
            log.warning("Trace: " + exceptionAsString);

            req.setAttribute("contentView", "/WEB-INF/Views/error/error.jsp");
            try {
                getServletContext().getRequestDispatcher(
                        "/WEB-INF/layout/Layout.jsp").forward(req, rsp);
            } catch (ServletException e1) {
                // TODO Auto-generated catch block
                e1.printStackTrace();
            } catch (IOException e1) {
                // TODO Auto-generated catch block
                e1.printStackTrace();
            }
            // e.printStackTrace(out);
        }
    }
}
